﻿import gnu.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.TooManyListenersException;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.*;
import java.awt.*;

public class ComListener implements Runnable {
	private static boolean DEBUG = true;
	private static int iPort = 1;
	private static String strIP = "";
	private static String portName = "";
	private static String sNachricht = "";
	private static BufferedWriter out = null;

	private static SimpleDateFormat formater = new SimpleDateFormat();

	CommPortIdentifier serialPortId;
	Enumeration<?> enumComm;
	SerialPort serialPort;
	InputStream inputStream;
	Boolean serialPortGeoeffnet = false;

	int baudrate = 9600;
	int dataBits = SerialPort.DATABITS_8;
	int stopBits = SerialPort.STOPBITS_1;
	int parity = SerialPort.PARITY_NONE;

	/**
	* Debugmeldungen fuer alle 
	*/
	public static void debug(String strMelder, String strMessage) {
		if (DEBUG) System.out.println(strMessage);
		try {
			Calendar cal = Calendar.getInstance();
			SimpleDateFormat formater = new SimpleDateFormat();
			out = new BufferedWriter(new FileWriter("debug.txt", true));
			out.write(formater.format(cal.getTime()) + ": " + strMelder + " - " + strMessage + "\r\n");
			out.close();
		} catch (Exception e){
			System.err.println("ERROR>> " + e.getMessage());
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		debug("COMLISTENER", "ComListener V0.9.9.9 (" + formater.format(Calendar.getInstance().getTime()) + ")");
		Datenbank db = new Datenbank();
		DEBUG = Boolean.valueOf(db.dbQueryConfig("comlistener_debug"));
		try {
			if (DEBUG) System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "UTF-8"));
		} catch (Exception err) {
			System.out.println("GEHT NICHT!!!!" + err);
		}
		if (DEBUG) System.out.println("!!!! Default Encoding = " + System.getProperty("file.encoding"));
		
		debug("COMLISTENER", "DEBUG>>    Parameter DEBUG: " + DEBUG);
		portName = db.dbQueryConfig("comlistener_port");
		strIP = db.dbQueryConfig("comlistener_sender_ip");
		iPort = Integer.parseInt(db.dbQueryConfig("comlistener_sender_port"));
		debug("COMLISTENER", "DEBUG>>       Parameter IP: " + strIP);
		debug("COMLISTENER", "DEBUG>> Parameter COM-Port: " + portName);
		debug("COMLISTENER", "DEBUG>>     Parameter Port: " + iPort);
		
		JFrame jf = new JFrame();
		JPanel jp = new JPanel(new GridLayout(4, 1));
		jf.getContentPane().add(jp);
		jf.setTitle("ComListener");
		jf.setLocation(0, 0);		
		jf.setSize(400, 400);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JLabel jl1 = new JLabel("      Parameter IP: " + strIP);
		JLabel jl2 = new JLabel("Parameter COM-Port: " + portName);
		JLabel jl3 = new JLabel("    Parameter Port: " + iPort);
		jp.add(jl1);
		jp.add(jl2);
		jp.add(jl3);
		jf.setVisible(true);
		
		Runnable runnable = new ComListener();
		new Thread(runnable).start();
		debug("COMLISTENER", "DEBUG>> main finished");
	}

	/**
	 * 
	 */
	public ComListener() {
	}

	public void run() {
		schliesseSerialPort();
		if (oeffneSerialPort(portName) != true) {
			debug("COMLISTENER", "ERROR>> oeffneSerialPort()");
		}
		debug("COMLISTENER", "DEBUG>> Warten auf Nachricht...");
		while (true) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
		}
	}

	boolean oeffneSerialPort(String portName) {
		Boolean foundPort = false;
		if (serialPortGeoeffnet != false) {
			debug("COMLISTENER", "ERROR>> Serialport bereits geöffnet");
			return false;
		}
		debug("COMLISTENER", "DEBUG>> Oeffne Serialport: " + portName);
		enumComm = CommPortIdentifier.getPortIdentifiers();
		while (enumComm.hasMoreElements()) {
			serialPortId = (CommPortIdentifier) enumComm.nextElement();
			debug("COMLISTENER", "DEBUG>>>" + serialPortId.getName());
			if (portName.contentEquals(serialPortId.getName())) {
				foundPort = true;
				break;
			}
		}
		if (foundPort != true) {
			debug("COMLISTENER", "ERROR>> Serialport nicht gefunden: " + portName);
			return false;
		}
		try {
			serialPort = (SerialPort) serialPortId.open("Oeffnen und Senden", 500);
		} catch (PortInUseException e) {
			debug("COMLISTENER", "ERROR>> Port belegt");
		}
		try {
			inputStream = serialPort.getInputStream();
		} catch (IOException e) {
			debug("COMLISTENER", "ERROR>> Keinen Zugriff auf InputStream");
		}
		try {
			serialPort.addEventListener(new serialPortEventListener());
		} catch (TooManyListenersException e) {
			debug("COMLISTENER", "ERROR>> TooManyListenersException für Serialport");
		}
		serialPort.notifyOnDataAvailable(true);
		try {
			serialPort.setSerialPortParams(baudrate, dataBits, stopBits, parity);
		} catch (UnsupportedCommOperationException e) {
			debug("COMLISTENER", "ERROR>> Konnte Schnittstellen-Paramter nicht setzen");
		}

		serialPortGeoeffnet = true;
		return true;
	}

	void schliesseSerialPort() {
		if (serialPortGeoeffnet == true) {
			debug("COMLISTENER", "DEBUG>> Schließe Serialport");
			serialPort.close();
			serialPortGeoeffnet = false;
		} else {
			debug("COMLISTENER", "ERROR>> Serialport bereits geschlossen");
		}
	}

	void serialPortDatenVerfuegbar() {
		try {
			byte[] data = new byte[1500];
			int num;
			while (inputStream.available() > 0) {
				num = inputStream.read(data, 0, data.length);
				debug("COMLISTENER", "DEBUG>> [TEIL_EMPFANG]: " + formater.format(Calendar.getInstance().getTime()) + " --- " + new String(data, 0, num));
				sNachricht = sNachricht + new String(data, 0, num);
			}
		} catch (IOException e) {
			debug("COMLISTENER", "ERROR>> Fehler beim Lesen empfangener Daten");
			return;
		}
		debug("COMLISTENER", "DEBUG>> [GESA_EMPFANG]: " + formater.format(Calendar.getInstance().getTime()) + " --- " + sNachricht);
		schreibeInDB(sNachricht);
	}

	class serialPortEventListener implements SerialPortEventListener {
		public void serialEvent(SerialPortEvent event) {
			debug("COMLISTENER", "DEBUG>> " + formater.format(Calendar.getInstance().getTime()) + " --- Neues Event: serialPortEventlistener");
			switch (event.getEventType()) {
			case SerialPortEvent.DATA_AVAILABLE:
				serialPortDatenVerfuegbar();
				break;
			case SerialPortEvent.BI:
				break;
			case SerialPortEvent.CD:
				break;
			case SerialPortEvent.CTS:
				break;
			case SerialPortEvent.DSR:
				break;
			case SerialPortEvent.FE:
				break;
			case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
				break;
			case SerialPortEvent.PE:
				break;
			case SerialPortEvent.RI:
				break;
			default:
			}
		}
	}

	/**
	 * Schreiben in DB
	 */
	private void schreibeInDB(String str) {
		schreibeInDB(str, 0);
	}
	private void schreibeInDB(String str, int iAlarm) {
		boolean bNachrichtEnde=false;
		int iCount=0;
		// 
		// Test ob Nachricht mit 00 endet, dann ist sie vollstaendig
		// Evtl. aber sind auch zwei Nachrichten enthalten
		//
		char cc = str.charAt(str.length()-1);
		if ((int)cc != 0) {
			debug("COMLISTENER", "DEBUG>> Kein 0x00 am Ende der Nachricht gefunden, stoppe Verarbeitung SchreibeInDB()");
			return;
		}

		for(int i = 0, size = str.length(); i < size; i++) {
			char c = str.charAt(i);
//			if (DEBUG) System.out.println("DEBUG>> ASCII: " + ((int)c));
			if ((int)c == 0) {
				bNachrichtEnde=true;
				if (i==(size-1)) {
					debug("COMLISTENER", "DEBUG>> ALLES GUT c: " + i + ", Size: " + size);
					str = str.substring(0, str.length()-1);							// Nullbyte entfernen
					break;
				} else {
					debug("COMLISTENER", "DEBUG>>      String zu kurz: " + i + ", Size: " + size);
					debug("COMLISTENER", "DEBUG>> Verarbeite nochmals: " + str.substring(i + 1, str.length()));
					debug("COMLISTENER", "DEBUG>>   Verarbeite direkt: " + str.substring(0, i - 1));
					if ((str.substring(0, i - 1).indexOf("Einsatzalarm 89") != -1) || (str.substring(0, i - 1).indexOf("Einzelfahrzeug 89") != -1)) {
						schreibeInDB(str.substring(i + 1, str.length()), iAlarm+1);			// Rest der Zeile nochmals rekursiv verarbeiten mit Alarm-Increase
					} else {
						schreibeInDB(str.substring(i + 1, str.length()), 0);				// Rest der Zeile nochmals rekursiv verarbeiten ohne Increase
					}
					str  = str.substring(0, i - 1);								// Nullbyte entfernen und ersten Teilstring verarbeiten
					debug("COMLISTENER", "DEBUG>> Verarbeite direkt2: " + str);
					break;
				}
			}
		}

		//
		// Pruefen ob das Ende der Nachricht erreicht ist
		//
		if (bNachrichtEnde) {
			debug("COMLISTENER", "DEBUG>> ENDE DER NACHRICHT GEFUNDEN");
			//
			// RAW Nachricht in DB schreiben und Mail versenden
			//
			Datenbank db = new Datenbank();
			db.dbInsertRaw(str);
			new SendMail(str);
			//
			// Nachricht aufsplitten
			//
			for(int i = 0, size = str.length()-1; i < size; i++) {
				char c1 = str.charAt(i);
				char c2 = str.charAt(i+1);
//				if (DEBUG) System.out.println("DEBUG>> ASCII: " + ((int)c1) + " " + ((int)c2));
				if (((int)c1 == 13) && ((int)c2 == 10)) {
					iCount++;
					debug("COMLISTENER", "DEBUG>> Suche nach 13/10 " + iCount);
					if (iCount==2) {
						debug("COMLISTENER", "DEBUG>> Suche nach 13/10 (2) Stelle: " + i);
						String strRIC = str.substring(i + 2, i + 2 + 3);						// + 2
						debug("COMLISTENER", "DEBUG>>            RIC: " + strRIC);
						db = new Datenbank();
						if (db.dbCheckRIC(strRIC) != true) {
              debug("COMLISTENER", "DEBUG>> Abbruch von RIC...?");
							return;
						}
					}
					if (iCount==3) {
						debug("COMLISTENER", "DEBUG>> Suche nach 13/10 (3) Stelle: " + i);
						str = str.substring(i + 2, str.length());						// + 2
						debug("COMLISTENER", "DEBUG>> Nachricht(Neu): " + str);
						break;
					}
				}
			}

			//
			// EMail versenden
			//
			//new SendMail(str);
			
			//
			// Wenn mehrere Alarme, dann ersetze Text 
			//
			if (iAlarm>0) {
				str = str.replaceFirst("Einsatz", "Vollalarm Einsatz");
			}

			//
			// In DB schreiben
			//
			//Datenbank db = new Datenbank();
			//db.dbInsertRaw(str);

			//
			// Nachricht versenden an Anzeige
			//
			TCPClient(str);

			sNachricht="";
		} else {
			debug("COMLISTENER", "DEBUG>> !!! KEIN ENDE DER NACHRICHT GEFUNDEN !!!" + sNachricht);
		}
	}

	/**
	 * Nachricht an Server senden
	 */
	private void TCPClient(String message) {
		debug("COMLISTENER", "DEBUG>> Versende: " + message);
		try {
			Socket s = new Socket(strIP, iPort);
			BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream(), "UTF-8"));
			out.write(message + '\n');
			out.flush();
			out.close();
			s.close();
//			DataOutputStream out = new DataOutputStream(s.getOutputStream());
//			BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
//			out.writeBytes(message + '\n');
//			in.close();
		} catch (IOException err) {
			debug("COMLISTENER", "Error: " + err);
		}
	}
}
